import pandas as pd
import itertools
from collections import Counter

# 读取Excel数据
def load_data(file_path):
    df = pd.read_excel(file_path)
    df = df[['issue', 'hundred', 'ten', 'one']]
    return df

# ===== 规则描述和函数 =====
kill_rule_desc = {
    'hundred': [
        "杀掉上一期百位号",
        "杀掉上上期百位号",
        "固定杀0",
        "固定杀9",
        "杀上一期百位邻号+1",
        "杀上一期百位邻号-1",
        "杀偶数",
        "杀奇数",
        "杀质数",
        "杀合数",
        "杀近期开出最多的百位号",
    ],
    'ten': [
        "杀掉上一期十位号",
        "杀掉上上期十位号",
        "固定杀5",
        "固定杀0",
        "杀上一期十位邻号+1",
        "杀上一期十位邻号-1",
        "杀偶数",
        "杀奇数",
        "杀质数",
        "杀合数",
        "杀近期开出最多的十位号",
    ],
    'one': [
        "杀掉上一期个位号",
        "杀掉上上期个位号",
        "固定杀3",
        "固定杀7",
        "杀上一期个位邻号+1",
        "杀上一期个位邻号-1",
        "杀偶数",
        "杀奇数",
        "杀质数",
        "杀合数",
        "杀近期开出最多的个位号",
    ]
}

sure_rule_desc = {
    'hundred': [
        "定胆上一期百位号",
        "定胆上上期百位号",
        "定胆0",
        "定胆9",
        "定胆上一期百位邻号+1",
        "定胆上一期百位邻号-1",
        "定胆偶数",
        "定胆奇数",
        "定胆质数",
        "定胆近期开出最多的百位号",
    ],
    'ten': [
        "定胆上一期十位号",
        "定胆上上期十位号",
        "定胆5",
        "定胆0",
        "定胆上一期十位邻号+1",
        "定胆上一期十位邻号-1",
        "定胆偶数",
        "定胆奇数",
        "定胆质数",
        "定胆近期开出最多的十位号",
    ],
    'one': [
        "定胆上一期个位号",
        "定胆上上期个位号",
        "定胆3",
        "定胆7",
        "定胆上一期个位邻号+1",
        "定胆上一期个位邻号-1",
        "定胆偶数",
        "定胆奇数",
        "定胆质数",
        "定胆近期开出最多的个位号",
    ]
}

# ===== 杀胆规则库 =====
kill_rules = {
    'hundred': [
        lambda df, idx: [df.iloc[idx-1]['hundred']] if idx > 0 else [],
        lambda df, idx: [df.iloc[idx-2]['hundred']] if idx > 1 else [],
        lambda df, idx: [0],
        lambda df, idx: [9],
        lambda df, idx: [(df.iloc[idx-1]['hundred']+1) % 10] if idx>0 else [],
        lambda df, idx: [(df.iloc[idx-1]['hundred']-1) % 10] if idx>0 else [],
        lambda df, idx: [n for n in range(10) if n % 2 == 0],
        lambda df, idx: [n for n in range(10) if n % 2 == 1],
        lambda df, idx: [2,3,5,7],
        lambda df, idx: [n for n in range(10) if n not in [2,3,5,7]],
        lambda df, idx: [Counter(df['hundred'][:idx]).most_common(1)[0][0]] if idx>5 else [],
    ],
    'ten': [
        lambda df, idx: [df.iloc[idx-1]['ten']] if idx > 0 else [],
        lambda df, idx: [df.iloc[idx-2]['ten']] if idx > 1 else [],
        lambda df, idx: [5],
        lambda df, idx: [0],
        lambda df, idx: [(df.iloc[idx-1]['ten']+1) % 10] if idx>0 else [],
        lambda df, idx: [(df.iloc[idx-1]['ten']-1) % 10] if idx>0 else [],
        lambda df, idx: [n for n in range(10) if n % 2 == 0],
        lambda df, idx: [n for n in range(10) if n % 2 == 1],
        lambda df, idx: [2,3,5,7],
        lambda df, idx: [n for n in range(10) if n not in [2,3,5,7]],
        lambda df, idx: [Counter(df['ten'][:idx]).most_common(1)[0][0]] if idx>5 else [],
    ],
    'one': [
        lambda df, idx: [df.iloc[idx-1]['one']] if idx > 0 else [],
        lambda df, idx: [df.iloc[idx-2]['one']] if idx > 1 else [],
        lambda df, idx: [3],
        lambda df, idx: [7],
        lambda df, idx: [(df.iloc[idx-1]['one']+1) % 10] if idx>0 else [],
        lambda df, idx: [(df.iloc[idx-1]['one']-1) % 10] if idx>0 else [],
        lambda df, idx: [n for n in range(10) if n % 2 == 0],
        lambda df, idx: [n for n in range(10) if n % 2 == 1],
        lambda df, idx: [2,3,5,7],
        lambda df, idx: [n for n in range(10) if n not in [2,3,5,7]],
        lambda df, idx: [Counter(df['one'][:idx]).most_common(1)[0][0]] if idx>5 else [],
    ]
}

# ===== 定胆规则库 =====
sure_rules = {
    'hundred': [
        lambda df, idx: [df.iloc[idx-1]['hundred']] if idx > 0 else [],
        lambda df, idx: [df.iloc[idx-2]['hundred']] if idx > 1 else [],
        lambda df, idx: [0],
        lambda df, idx: [9],
        lambda df, idx: [(df.iloc[idx-1]['hundred']+1) % 10] if idx>0 else [],
        lambda df, idx: [(df.iloc[idx-1]['hundred']-1) % 10] if idx>0 else [],
        lambda df, idx: [n for n in range(10) if n % 2 == 0],
        lambda df, idx: [n for n in range(10) if n % 2 == 1],
        lambda df, idx: [2,3,5,7],
        lambda df, idx: [Counter(df['hundred'][:idx]).most_common(1)[0][0]] if idx>5 else [],
    ],
    'ten': [
        lambda df, idx: [df.iloc[idx-1]['ten']] if idx > 0 else [],
        lambda df, idx: [df.iloc[idx-2]['ten']] if idx > 1 else [],
        lambda df, idx: [5],
        lambda df, idx: [0],
        lambda df, idx: [(df.iloc[idx-1]['ten']+1) % 10] if idx>0 else [],
        lambda df, idx: [(df.iloc[idx-1]['ten']-1) % 10] if idx>0 else [],
        lambda df, idx: [n for n in range(10) if n % 2 == 0],
        lambda df, idx: [n for n in range(10) if n % 2 == 1],
        lambda df, idx: [2,3,5,7],
        lambda df, idx: [Counter(df['ten'][:idx]).most_common(1)[0][0]] if idx>5 else [],
    ],
    'one': [
        lambda df, idx: [df.iloc[idx-1]['one']] if idx > 0 else [],
        lambda df, idx: [df.iloc[idx-2]['one']] if idx > 1 else [],
        lambda df, idx: [3],
        lambda df, idx: [7],
        lambda df, idx: [(df.iloc[idx-1]['one']+1) % 10] if idx>0 else [],
        lambda df, idx: [(df.iloc[idx-1]['one']-1) % 10] if idx>0 else [],
        lambda df, idx: [n for n in range(10) if n % 2 == 0],
        lambda df, idx: [n for n in range(10) if n % 2 == 1],
        lambda df, idx: [2,3,5,7],
        lambda df, idx: [Counter(df['one'][:idx]).most_common(1)[0][0]] if idx>5 else [],
    ]
}

# ===== 规则正确率计算 =====
def calc_rule_accuracy(df, rules, position, mode='kill'):
    results = []
    for idx_rule, rule in enumerate(rules[position]):
        correct = 0
        total = 0
        for idx in range(len(df)):
            target = df.iloc[idx][position]
            nums = rule(df, idx)
            if not nums:
                continue
            total += 1
            if mode == 'kill':
                if target not in nums:
                    correct += 1
            elif mode == 'sure':
                if target in nums:
                    correct += 1
        accuracy = correct / total if total > 0 else 0
        results.append({
            'rule_index': idx_rule,
            'accuracy': accuracy,
            'desc': (kill_rule_desc if mode == 'kill' else sure_rule_desc)[position][idx_rule]
        })
    results.sort(key=lambda x: x['accuracy'], reverse=True)
    return results

# ===== 下一期号码推荐 =====
def recommend_numbers(df, kill_num, sure_num):
    recommend_result = {}
    used_rules = {}
    for pos in ['hundred', 'ten', 'one']:
        kill_acc = calc_rule_accuracy(df, kill_rules, pos, 'kill')
        kill_selected = kill_acc[:kill_num[pos]]
        kill_numbers = set()
        for r in kill_selected:
            nums = kill_rules[pos][r['rule_index']](df, len(df)-1)
            kill_numbers.update(nums)
        sure_acc = calc_rule_accuracy(df, sure_rules, pos, 'sure')
        sure_selected = sure_acc[:sure_num[pos]]
        sure_numbers = set()
        for r in sure_selected:
            nums = sure_rules[pos][r['rule_index']](df, len(df)-1)
            sure_numbers.update(nums)
        recommend_result[pos] = {
            'kill': sorted(set(kill_numbers)),
            'sure': sorted(set(sure_numbers))
        }
        used_rules[pos] = {
            'kill': kill_selected,
            'sure': sure_selected
        }
    return recommend_result, used_rules

# ===== 投注组合 =====
def generate_combinations(recommend_result):
    possible_h = [n for n in range(10) if n not in recommend_result['hundred']['kill']]
    possible_t = [n for n in range(10) if n not in recommend_result['ten']['kill']]
    possible_o = [n for n in range(10) if n not in recommend_result['one']['kill']]

    if recommend_result['hundred']['sure']:
        possible_h = [n for n in possible_h if n in recommend_result['hundred']['sure']]
    if recommend_result['ten']['sure']:
        possible_t = [n for n in possible_t if n in recommend_result['ten']['sure']]
    if recommend_result['one']['sure']:
        possible_o = [n for n in possible_o if n in recommend_result['one']['sure']]

    combinations = list(itertools.product(possible_h, possible_t, possible_o))
    return combinations

# ===== 输出排行榜 =====
def print_accuracy_tables(df):
    for pos in ['hundred', 'ten', 'one']:
        print(f"\n=== {pos}位 杀胆规则排行榜 ===")
        kill_acc = calc_rule_accuracy(df, kill_rules, pos, 'kill')
        for r in kill_acc:
            print(f"规则#{r['rule_index']+1}: {r['desc']} -> 正确率 {r['accuracy']:.2%}")

        print(f"\n=== {pos}位 定胆规则排行榜 ===")
        sure_acc = calc_rule_accuracy(df, sure_rules, pos, 'sure')
        for r in sure_acc:
            print(f"规则#{r['rule_index']+1}: {r['desc']} -> 正确率 {r['accuracy']:.2%}")

# ===== 主程序 =====
if __name__ == "__main__":
    file_path = "3d.xlsx"
    df = load_data(file_path)

    kill_num = {'hundred': 5, 'ten': 5, 'one': 5}
    sure_num = {'hundred': 3, 'ten': 3, 'one': 3}

    print_accuracy_tables(df)

    recommend_result, used_rules = recommend_numbers(df, kill_num, sure_num)

    print("\n=== 下一期推荐 ===")
    for pos in ['hundred', 'ten', 'one']:
        # print(f"{pos}位 -> 杀胆: {recommend_result[pos]['kill']}, 定胆: {recommend_result[pos]['sure']}")
        print(f"{pos}位 -> 杀胆: {recommend_result[pos]['kill']}")
        print(f"  使用的杀胆规则:")
        for r in used_rules[pos]['kill']:
            print(f"    {r['desc']} -> 正确率 {r['accuracy']:.2%}")
        # print(f"  使用的定胆规则:")
        # for r in used_rules[pos]['sure']:
        #     print(f"    {r['desc']} -> 正确率 {r['accuracy']:.2%}")

    combinations = generate_combinations(recommend_result)
    total_bets = len(combinations)
    total_cost = total_bets * 2
    win_probability = 1 / total_bets if total_bets > 0 else 0

    print(f"\n投注组合数: {total_bets}")
    print(f"所需彩金: {total_cost} 元")
    print(f"预计中奖概率: {win_probability:.4%}")
